<?php
class Wx{
    public static $appid='wxd69b753bd728ec58';
    public static $mch_id='1495003752';
	//以下的key需要在微信端设置为固定的值
    public static $key='3a4298ff9fc91c122799b163c1004cc3';
	static $instance;
	public $notify_url="http://www.shenlong.com/index.php/info/notifyUrl";
	private function __construct($appid, $mch_id, $key) {
	    if (is_string($appid) && is_string($mch_id)) {
	        $this->appid = $appid;
	        $this->mch_id = $mch_id;
	        $this->key = $key;
	    }
	}
	public static function getInstance() {
	    if(self::$instance == null) {
	        self::$instance = new Self(self::$appid,self::$mch_id,self::$key);
	    }
	    return self::$instance;
	}

	public function sendRequest($data) {
	    $data = $this->setSendData($data); 
	      //获取要发送的数据
	    $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
	    $content = $this->http_req('https','post',$url,$data);          //设置请求地址
	    return $this->xmlToObject($content);      //返回请求到的数据
	}
	/**
	 * 拼装请求的数据
	 * @return  String 拼装完成的数据
	 */
	
	function setSendData($data) {
	    $sTpl = "<xml>
	                        <appid><![CDATA[%s]]></appid>
	                        <body><![CDATA[%s]]></body>
	                        <mch_id><![CDATA[%s]]></mch_id>
	                        <nonce_str><![CDATA[%s]]></nonce_str>
	                        <notify_url><![CDATA[%s]]></notify_url>
	                        <out_trade_no><![CDATA[%s]]></out_trade_no>
	                        <spbill_create_ip><![CDATA[%s]]></spbill_create_ip>
	                        <total_fee><![CDATA[%d]]></total_fee>
	                        <trade_type><![CDATA[%s]]></trade_type>
	                        <sign><![CDATA[%s]]></sign>
	                    </xml>";                          //xml数据模板
	    $nonce_str = $this->getNonceStr();        //调用随机字符串生成方法获取随机字符串
	    $data['appid'] = $this->appid;
	    $data['mch_id'] = $this->mch_id;
	    $data['nonce_str'] = $nonce_str;
	    $data['notify_url'] = $this->notify_url;
	    $data['trade_type'] = 'APP';      //将参与签名的数据保存到数组
	    $data['spbill_create_ip'] = $_SERVER['REMOTE_ADDR'];
	    // 注意：以上几个参数是追加到$data中的，$data中应该同时包含开发文档中要求必填的剔除sign以外的所有数据
	    $sign = $this->getSign($data);        //获取签名
	    $data = sprintf($sTpl, $data['appid'], $data['body'], $this->mch_id, $nonce_str, $this->notify_url, $data['out_trade_no'], $_SERVER['REMOTE_ADDR'], $data['total_fee'], "APP", $sign);
	    return $data;
	}
	public function xmlToObject($xmlStr) {
	    if (!is_string($xmlStr) || empty($xmlStr)) {
	        return false;
	    }
	    // 由于解析xml的时候，即使被解析的变量为空，依然不会报错，会返回一个空的对象，所以，我们这里做了处理，当被解析的变量不是字符串，或者该变量为空，直接返回false
	    $postObj = simplexml_load_string($xmlStr, 'SimpleXMLElement', LIBXML_NOCDATA);
	    $postObj = json_decode(json_encode($postObj));
	    //将xml数据转换成对象返回
	    return $postObj;
	}
	
	private function getNonceStr() {
	    $code = "";
	    for ($i=0; $i > 10; $i++) { 
	        $code .= mt_rand(1000);        //获取随机数
	    }
	    $nonceStrTemp = md5($code);
	    $nonce_str = mb_substr($nonceStrTemp, 5,37);      //MD5加密后截取32位字符
	    return $nonce_str;
	}

	function getSign($params) {
	    ksort($params);        //将参数数组按照参数名ASCII码从小到大排序
	    foreach ($params as $key => $item) {
	        if (!empty($item)) {         //剔除参数值为空的参数
	            $newArr[] = $key.'='.$item;     // 整合新的参数数组
	        }
	    }
	    $stringA = implode("&", $newArr);         //使用 & 符号连接参数
	    $stringSignTemp = $stringA."&key=".$this->key;        //拼接key
	    $stringSignTemp = MD5($stringSignTemp);       //将字符串进行MD5加密
	    $sign = strtoupper($stringSignTemp);      //将所有字符转换为大写
	    return $sign;
	}
	public function setNotifyUrl($url) {
	    if (is_string($url)) {
	        $this->notify_url = $url;
	    }
	}
	public function getNotifyUrl() {
	    return  $this->notify_url;
	}

	function http_req($http_type, $method, $url, $data)
	{
		$ch = curl_init();
		if (strstr($http_type, 'https'))
		{
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); 
		}   

		if ($method == 'post')
		{
			curl_setopt($ch, CURLOPT_POST, 1); 
			curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
		} else
		{
			$url = $url . '?' . $data;
		}		
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HEADER, 0); 
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
		curl_setopt($ch, CURLOPT_TIMEOUT,100000);//超时时间

		try
		{
			$ret=curl_exec($ch);
		}catch(Exception $e)
		{
			curl_close($ch);
			return json_encode(array('ret'=>0,'msg'=>'failure'));
		}
		curl_close($ch);
		return $ret;
	}


}
?>

